using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using System.IO;
using System.Text;
using System.Xml;

namespace Workflows.Designer.OfficeUtil
{
    public class PictureWriter
    {
        private const string WordMLNS = "http://schemas.microsoft.com/office/word/2003/wordml";
        private const string VMLNS = "urn:schemas-microsoft-com:vml";
        private const string OfficeNS = "urn:schemas-microsoft-com:office:office";

        private NameValueCollection _namespaces;
        public NameValueCollection Namespaces
        {
            get { return _namespaces; }
            set { _namespaces = value; }
        }
        private int _Width;
        public int Width
        {
            get { return _Width; }
            set { _Width = value; }
        }
        private int _Height;
        public int Height
        {
            get { return _Height; }
            set { _Height = value; }
        }
        private byte[] _Data;
        private string _Title;
        public string Title
        {
            get { return _Title; }
            set { _Title = value; }
        }
        private string _Name;
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }
        private string _Extension;
        public string Extension
        {
            get { return _Extension; }
            set { _Extension = value; }
        }
        protected PictureWriter()
        {
            this._namespaces = new NameValueCollection();
            this._namespaces.Add("w", WordMLNS);
            this._namespaces.Add("v", VMLNS);
            this._namespaces.Add("o", OfficeNS);
        }

        public PictureWriter(string path, string title)
            : this()
        {
            this._Name = Path.GetFileName(path);
            this._Title = title;
            FileStream fs = File.OpenRead(path);
            int len = (int) fs.Length;
            this._Data = new byte[len];
            fs.Read(this._Data, 0, len);
            fs.Close();
            Bitmap bmp = new Bitmap(path);
            this._Width = bmp.Size.Width;
            this._Height = bmp.Size.Height;
            SetExtension(bmp.RawFormat);
            bmp.Dispose();
            bmp = null;
        }

        public PictureWriter(string path)
            : this(path, Path.GetFileNameWithoutExtension(path))
        {
        }

        public PictureWriter(Image img, string title, string name)
            : this()
        {
            this._Title = title;
            this._Name = name;
            this._Width = img.Size.Width;
            this._Height = img.Size.Height;
            MemoryStream strm = new MemoryStream();
            img.Save(strm, System.Drawing.Imaging.ImageFormat.Bmp);
            this._Data = strm.ToArray();
            strm.Close();
            SetExtension(img.RawFormat);
        }

        private void SetExtension(System.Drawing.Imaging.ImageFormat fmt)
        {
            if (fmt == System.Drawing.Imaging.ImageFormat.Jpeg)
            {
                this._Extension = ".jpg";
            }
            else if (fmt == System.Drawing.Imaging.ImageFormat.Gif)
            {
                this._Extension = ".gif";
            }
            else if (fmt == System.Drawing.Imaging.ImageFormat.Bmp)
            {
                // if blank then Word seems OK at guessing
                this._Extension = ".bmp";
            }
            else
            {
                this._Extension = "";
            }
        }

        protected void WriteDoc(XmlTextWriter wtr)
        {
            wtr.WriteStartDocument();
            wtr.WriteProcessingInstruction("mso-application", "progid=\"Word.Document\"");
            wtr.WriteStartElement("w", "wordDocument", WordMLNS);
            foreach (string prefix in _namespaces.AllKeys)
            {
                wtr.WriteAttributeString("xmlns", prefix, null, _namespaces[prefix]);
            }

            wtr.WriteStartElement("body", WordMLNS);
            WritePict(wtr);
            wtr.WriteEndElement();
            wtr.WriteEndElement();
            wtr.WriteEndDocument();
        }

        protected void WritePict(XmlTextWriter wtr)
        {
            if (this._Data == null)
            {
                return;
            }
            wtr.WriteStartElement("pict", WordMLNS);
            wtr.WriteStartElement("binData", WordMLNS);
            wtr.WriteAttributeString("name", WordMLNS, string.Format("wordml://{0}{1}", this._Name, this._Extension));
            wtr.WriteBase64(this._Data, 0, this._Data.Length);
            wtr.WriteEndElement();
            wtr.WriteStartElement("shape", VMLNS);
            wtr.WriteAttributeString("id", "_x0000_" + this._Name);
            wtr.WriteAttributeString("style", string.Format("width:{0}px;height:{1}px", this._Width, this._Height));
            wtr.WriteStartElement("imagedata", VMLNS);
            wtr.WriteAttributeString("src", string.Format("wordml://{0}{1}", this._Name, this._Extension));
            wtr.WriteAttributeString("title", OfficeNS, this._Title);
            wtr.WriteEndElement();
            wtr.WriteEndElement();
            wtr.WriteEndElement();
        }

        public override string ToString()
        {
            MemoryStream strm = new MemoryStream();
            XmlTextWriter wtr = null;
            try
            {
                wtr = new XmlTextWriter(strm, System.Text.Encoding.ASCII);
                WriteDoc(wtr);
            }
            finally
            {
                wtr.Close();
                strm.Close();
            }

            return ASCIIEncoding.ASCII.GetString(strm.ToArray());
        }
    }
}
